一份行情要送給機房裡幾十台機器。最直覺的做法是一台一台送,每台一份。這樣為什麼不行?
用昨天的算式就看得出來,取 1518 bytes 這種最大的 frame 算上限,10G 的線推一份加上線上開銷是 1230.4 ns。四十個訂閱者,四十份複本全部要從同一條線推出去:
1230.4 ns * 40 = 49216 ns ≈ 49 µs
一台低延遲交換器的 port-to-port 是幾百 ns 的量級,這裡光是把複本推上線就吃掉 49 µs。排最後那台要等前面三十九份推完才輪到,比第一台晚 48 µs,而每個人晚的量還不一樣,排序是發送端決定的。
多播把這件事拿掉:發送端只推一份,複製交給交換器。
多播位址不對應任何一張網卡,它是一個群組編號,接收端要「訂閱」才會收到。交換器收到一份,會去查自己那張表看哪些 port 訂了這個群組,接著往那些 port 各送一份。複製發生在轉發引擎裡,不佔發送端的線。
所以四十個訂閱者跟一個訂閱者,發送端的成本一樣,這是多播在低延遲環境唯一真正重要的性質。順帶解決公平性:那些 port 是並行發送出去的,不用一個一個等排隊。
交換器是二層設備,本來看不懂三層的 IGMP。IGMP snooping 就是讓它偷看這些訊息,自己建一張「哪個 port 訂了哪個群組」的表。這是關鍵零件,也是維運上最容易出事的地方。
沒開 snooping: 交換器不知道該往哪送,只好當廣播處理,往 VLAN 裡所有 port 都送一份,也就是洪泛。那些流量一定佔掉線的頻寬;能不能在網卡的多播過濾器就擋掉要看那張卡,擋不掉的一路送進 kernel 才被丟。一台不相關的機器因為別人的行情而變慢,這種故障很難查,因為故障現象跟根本原因不在同一台設備上。
snooping 需要有人問。 表裡的記錄會過期,要靠 querier 週期性地問「還有誰在訂」來續。純二層網段裡沒有路由器,就得指定一台交換器當 querier。沒有 querier,表會慢慢空掉然後退回洪泛。
| 狀況 | 故障現象 | 先查什麼 |
|---|---|---|
| snooping 沒開或退回洪泛 | 不相關的機器收到不該收的流量,網卡計數器爆增 | snooping 有沒有開、querier 在不在 |
| 群組洩漏 | 某個 port 一直收到已經沒人訂的群組 | 那個 port 有沒有被設成靜態的 router port、表裡的記錄有沒有過期 |
| 爆量 | 出口佇列被塞滿,延遲跳升 | 哪幾個群組同時在爆、它們是不是走同一個出口 |
前兩種是設定問題,查得到就修得掉。第三種比較麻煩。
爆量的本質是昨天那四塊裡的佇列。多播把複製成本從發送端移到交換器,但沒有移走出口的佇列:一個 port 上訂了幾百個群組,開盤那一刻它們同時醒過來,全部要從這一個 port 出去。
所以監控要盯兩件事,而且是兩個不同的東西。
訂閱關係盯「有沒有變」。 snooping 表平常應該是穩定的,機器上下線才會動。它自己變了就是有東西不對,這要當設定漂移看,不是當流量看,實務上就是定期拉下來跟基線比。
出口盯佇列。 跟昨天的結論是同一件事,只是多播讓它更容易發生:單播下一個發送端塞一個出口,多播下一個發送端可以同時塞很多個。
門檻怎麼從量到的雜訊推出來,Day 6 已經示範過一次。這裡少的是多播自己的基線,那要等後面的實測。現在能寫的判斷條件是這樣:
| 看到什麼 | 大概是什麼 |
|---|---|
| 沒訂閱的 port 有多播流量 | snooping 或 querier 出問題 |
| 訂閱表的內容自己變了 | 設定漂移,去查誰動了什麼 |
| 延遲跳升但錯誤計數器乾淨 | 佇列,去查哪些群組在同一個出口 |
多播爆量在交換器上到底會留下什麼痕跡,我會在後面的實測裡弄出來看。
明天講 cut-through 跟 store-and-forward,也就是為什麼有的交換器延遲跟封包大小無關。